// auth.ts
import { jwtDecode } from "jwt-decode";
import axios from "axios";
import store from "@/store"; // 引入 Vuex store

import { DecodedToken } from "@/types/userTypes"; // 引入用户类型

let refreshTimer: ReturnType<typeof setTimeout> | null = null;
let activityTimer: ReturnType<typeof setTimeout> | null = null;
let waitActivityTimer: ReturnType<typeof setTimeout> | null = null;
let pollingInterval: ReturnType<typeof setInterval> | null = null; // 定义 pollingInterval
let hasAddedListener = false; // 标志变量，确保监听器只添加一次

// 获取 token 的函数
export const getAccessToken = async (): Promise<string | null> => {
  const token = localStorage.getItem("accessToken");
  if (!token) {
    throw new Error("未找到 token，请登录");
    // return null;
  }
  console.log("获取 token 成功", token);
  const decoded: DecodedToken = jwtDecode(token);

  // 检查 token 是否过期
  if (isTokenExpired(decoded.exp)) {
    console.error("Token 已过期，请重新登录");
    // 自动登出
    store.dispatch("users/logout"); // 清除用户状态
    return null;
  }
  const expirationTime = Math.floor(Date.now() / 1000) + 10.15 * 60; // 12分钟
  // 启动刷新定时器
  startRefreshTimer(expirationTime);

  return token;
};

const isTokenExpired = (expiration: number): boolean => {
  return expiration * 1000 < Date.now();
};

// 刷新 token 的函数
const refreshAccessToken = async (needThrow = false): Promise<void> => {
  try {
    const response = await axios.post("/api/refresh-token"); // 替换为实际 API
    const newToken: string = response.data.data.accessToken;

    // 存储新的 token
    localStorage.setItem("accessToken", newToken);
    console.log("Token 刷新成功");

    // 更新 Vuex 状态（假设用户数据来自新 token）
    const decoded: DecodedToken = jwtDecode(newToken);
    store.dispatch("users/login", {
      userData: {
        id: decoded.id,
        name: decoded.name,
        email: decoded.email,
        account: decoded.account,
        mode: decoded.mode,
      },
      token: newToken,
    });

    // 成功刷新后，清除轮询定时器
    if (pollingInterval) {
      clearInterval(pollingInterval);
      pollingInterval = null; // 清除引用
    }

    // 启动新的定时器
    startRefreshTimer(decoded.exp);
  } catch (error) {
    console.error("刷新 token 失败", error);
    if (needThrow) {
      throw error;
    }
    // 自动登出
    // store.dispatch('users/logout'); // 清除用户状态
    // 处理失败，例如重定向到登录
  }
};

// 启动定时器以在 token 快过期时刷新 token
const startRefreshTimer = (expiration: number): void => {
  if (refreshTimer) {
    clearTimeout(refreshTimer); // 清除之前的定时器
  }

  const timeUntilExpiration = expiration * 1000 - Date.now(); // 提前 5 分钟
  if (timeUntilExpiration > 5 * 60 * 1000) {
    // const timeUntilExpiration2 = 300000  //测试：10秒刷新1次
    // 计算刷新时间
    const refreshTime = new Date(
      Date.now() + timeUntilExpiration - 5 * 60 * 1000
    );
    console.log(
      `距离 token 超期还有 ${
        timeUntilExpiration / 1000
      } 秒，计划在 ${refreshTime.toLocaleString("zh-CN", {
        year: "numeric",
        month: "2-digit",
        day: "2-digit",
        hour: "2-digit",
        minute: "2-digit",
        second: "2-digit",
        hour12: false,
      })} 进行刷新`
    );

    // 距离过期时间大于 5 分钟，设置定时器
    refreshTimer = setTimeout(async () => {
      try {
        await refreshAccessToken(true); // 尝试刷新 token
      } catch (error) {
        console.error("刷新 token 失败:", error);
        // 如果刷新失败，重新启动定时器以继续尝试
        startRefreshTimer(expiration); // 重新设置定时器
      }
    }, timeUntilExpiration - 5 * 60 * 1000); // 提前 5 分钟刷新
  } else if (timeUntilExpiration > 0) {
    // 如果距离过期时间不足 5 分钟但仍大于 0
    console.warn(
      "Token 已经过期或不足 5 分钟，进入每 30 秒轮询一次自动刷新 token 的状态，直到 token 过期"
    );

    if (!pollingInterval) {
      // 防止重复创建轮询定时器
      pollingInterval = setInterval(async () => {
        const newTimeUntilExpiration = expiration * 1000 - Date.now();
        if (newTimeUntilExpiration > 0) {
          // 尝试刷新 token
          try {
            await refreshAccessToken(); // 尝试刷新 token
          } catch (error) {
            console.error("刷新 token 失败:", error);
          }
        } else {
          if (pollingInterval) {
            clearInterval(pollingInterval);
            pollingInterval = null; // 清除引用
          }
          console.error("Token 已经过期，请重新登录");
          store.dispatch("users/logout"); // 清除用户状态
        }
      }, 30000); // 每 30 秒检查一次
    }
  } else {
    console.error("Token 已经过期，请重新登录");
    // 自动登出
    store.dispatch("users/logout"); // 清除用户状态
  }
  // 添加用户活动监听
  if (timeUntilExpiration > 5 * 60 * 1000) {
    startActivityListener(expiration);
  }
};

// 启动用户活动监听
const startActivityListener = (expiration: number) => {
  let hasRefreshedToken = false; // 标志变量，初始为 false，用于检测 token 是否已刷新
  console.log("启动用户活动监听器");
  const handleUserActivity = () => {
    const timeUntilExpiration = expiration * 1000 - Date.now();

    // 检查 token 是否在 10 分钟内过期
    if (timeUntilExpiration > 0 && timeUntilExpiration <= 10 * 60 * 1000) {
      if (!hasRefreshedToken) {
        // 只有第一次活动时刷新 token
        console.log("用户活动检测到，准备刷新 token");
        refreshAccessToken(); // 刷新 token
        hasRefreshedToken = true; // 设置为 true，防止后续刷新
      }
    } else {
      // 如果不在 10 分钟内过期，重置标志
      hasRefreshedToken = false; // 重置 token 刷新标志
    }

    // 每次用户活动时重置活动定时器
    if (activityTimer) {
      console.log("每次用户活动时重置活动定时器");
      clearTimeout(activityTimer);
      document.removeEventListener("mousemove", handleUserActivity);
      document.removeEventListener("keydown", handleUserActivity);
      hasAddedListener = false; // 重置标志以便下次可以添加
    }

    // 设置定时器，10分钟内无活动则清除监听
    activityTimer = setTimeout(() => {
      console.log("用户无活动，清除活动监听器");
      document.removeEventListener("mousemove", handleUserActivity);
      document.removeEventListener("keydown", handleUserActivity);
      hasAddedListener = false; // 重置标志以便下次可以添加
    }, 10 * 60 * 1000); // 10分钟
  };

  const timeUntilExpiration = expiration * 1000 - Date.now();
  // 检查有效期，如果剩余时间小于或等于 10 分钟，才添加监听器
  if (
    timeUntilExpiration > 0 &&
    timeUntilExpiration <= 10 * 60 * 1000 &&
    !hasAddedListener
  ) {
    console.log("添加用户活动监听器");
    document.addEventListener("mousemove", handleUserActivity);
    document.addEventListener("keydown", handleUserActivity);
    hasAddedListener = true; // 设置标志，禁止重复添加
  } else if (!hasAddedListener) {
    waitActivityTimer = setTimeout(() => {
      console.log("添加用户活动监听器");
      document.addEventListener("mousemove", handleUserActivity);
      document.addEventListener("keydown", handleUserActivity);
      hasAddedListener = true; // 设置标志，禁止重复添加
    }, timeUntilExpiration - 10 * 60 * 1000); // 10秒后再添加
  }

  // 如果监听器已经被添加，直接初始化活动检测
  if (hasAddedListener) {
    handleUserActivity(); // 立即调用以初始化
  }
};

export const stopRefreshTimer = (): void => {
  if (refreshTimer) {
    clearTimeout(refreshTimer);
    refreshTimer = null;
  }
  if (activityTimer) {
    clearTimeout(activityTimer);
    activityTimer = null;
  }
  if (pollingInterval) {
    clearInterval(pollingInterval);
    pollingInterval = null;
  }
  if (waitActivityTimer) {
    clearTimeout(waitActivityTimer);
    waitActivityTimer = null;
  }
  console.log("停止刷新定时器");
};
